﻿namespace Text2Rss.Web.Services
{
	#region Using Directives
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using NHibernate;
	using NHibernate.Criterion;
	using Text2Rss.Web.Models;
	#endregion

	/// <summary>
	/// Performs operations with feeds
	/// </summary>
	public class FeedService : BaseService
	{
		#region Fields

		private Feed feed;
		private IFileStorage storage;
		
		#endregion // Fields

		#region Constructor

		/// <summary>
		/// Initializes a new instance of FeedService
		/// </summary>
		/// <param name="session">Current session</param>
		/// <param name="feed">Feed to process</param>
		/// <param name="storage">File storage</param>
		public FeedService(ISession session, Feed feed, IFileStorage storage)
			: base(session)
		{
			this.feed = feed;
			this.storage = storage;
		}

		#endregion // Constructor

		#region Methods

		/// <summary>
		/// Loads posts
		/// </summary>
		/// <param name="feed">Feed to load</param>
		/// <param name="count">Max count of posts</param>
		/// <returns>Loaded posts</returns>
		public IEnumerable<Post> LoadPosts(int count)
		{
			PublishPostIfNeeded();

			return Session.CreateCriteria<Post>()
				.Add(Restrictions.Eq("Feed", feed))
				.AddOrder(Order.Desc("DateTime"))
				.List<Post>();
		}

		/// <summary>
		/// Publishes the next post if time is achieved.
		/// </summary>
		/// <returns></returns>
		public bool PublishPostIfNeeded()
		{
			var timeSpan = DateTime.Now - GetLastPublishDate();

			if (feed.PublishInterval > timeSpan.TotalSeconds)
			{
				return PublishPost();
			}

			return false;
		}

		public bool PublishPost()
		{
			using (var file = storage.OpenFile(feed.SourceFile))
			{
				var textParser = new TextParser(file);

				if (!textParser.GoTo(feed.CurrentPosition)) // The file is over
				{
					// TODO: add ability to turn the feed off
					return false;
				}

				if (!textParser.ReadText(feed.PostSize))
				{
					return false;
				}

				Session.Save(new Post
				{
					Feed = feed,
					DateTime = DateTime.Now,
					Content = textParser.Text
				});

				feed.CurrentPosition = textParser.CurrentPosition;

				Session.Save(feed);
			}

			return true;
		}

		private DateTime GetLastPublishDate()
		{
			var result = Session.CreateCriteria<Post>()
				.Add(Restrictions.Eq("Feed", feed))
				.SetProjection(Projections.Max("DateTime"))
				.UniqueResult<DateTime?>();

			if(!result.HasValue)
			{
				return new DateTime(1900, 1, 1);
			}

			return result.Value;
		}

		#endregion // Methods
	}
}